import ts from 'typescript'
import { outputLog, getTsConfig, getEnterFieldMap } from '../utils'
import { TransformFileAsyncOptions } from '../interface'

export async function TsTransform(
  fileNames: string[],
  entry: string,
  options: TransformFileAsyncOptions,
): Promise<void> {
  let tsOptions = getTsConfig(entry).compilerOptions
  let { outDir, disableBabel } = options || {}
  return new Promise(async (resolve, reject) => {
    // Create a Program with an in-memory emit
    const createdFiles: Record<string, string> = {}
    tsOptions = {
      ...tsOptions,
      outDir,
      target: tsOptions.target || ts.ScriptTarget.ESNext,
    }
    const host = ts.createCompilerHost(tsOptions, true)
    // ts.getParsedCommandLineOfConfigFile('', tsOptions, host)
    host.readFile = (file) => {
      const result = ts.sys.readFile(file)
      return result
    }
    host.writeFile = (fileName: string, contents: string) => {
      return (createdFiles[fileName] = contents)
    }

    const program = ts.createProgram(fileNames, tsOptions, host)

    // Prepare and emit the `d.ts` files
    program.emit()
    const mapField = getEnterFieldMap(
      fileNames,
      Object.keys(createdFiles),
      entry,
      outDir,
    )

    await Promise.all(
      Object.keys(createdFiles).map(async (filepath) => {
        try {
          if (disableBabel && !/\.d\.ts$/.test(filepath)) {
            ts.sys.writeFile(filepath, createdFiles[filepath])
            if (/\.(js|jsx)$/.test(filepath)) {
              outputLog(mapField.get(filepath), filepath)
            }
          }
          if (/\.d\.ts$/.test(filepath)) {
            if (new RegExp(`${outDir}`).test(filepath)) {
              ts.sys.writeFile(filepath, createdFiles[filepath])
              outputLog(mapField.get(filepath), filepath)
            }
          }
        } catch (error) {
          reject(error)
        }
      }),
    )
    resolve()
  })
}
